package org.jprobe.reflect.classpath;

import java.util.List;
import java.util.Set;
/**
 * provides specifications of ClassPath data structure
 * @author Hussain Al-Mutawa
 * @version 1.0
 */
public interface ClassPathInterface {
	/**
	 *  provides list of packages in the class path branching off
	 *  a map of the classes loaded in the classpath, the value for
	 *  each class is the jar from which the class was loaded
	 * @return set of packages
	 */
	Set<String> getPackages();
	/**
	 * adds a package to the classpath
	 * @param packageInterface a package
	 */
	void addPackage(PackageInterface packageInterface);
	/**
	 * gets classpath entries
	 * @return set of paths to classes in the classpath
	 */
	Set<String> getEntries();
	/**
	 * adds an entry to the classpath
	 * @param packageInterface a package
	 */
	void addEntry(String entry);
	/**
	 * gets a package by its name
	 * @param name the name of the package
	 * @return package data structur
	 */
	PackageInterface getPackage(String name);
	/**
	 * determins if the classpath has given class
	 * @param classBinaryName the full name of class specified by package.class, eg. <code>java.lang.Object</code>
	 * @return
	 */
	boolean hasClass(String classBinaryName);

	/**
	 * determines if a class is from built in java runtime libraries, such as java.lang.*
	 * @param clazz a class to be tested
	 * @return true if from JRE, false otherwise
	 */
	boolean isRuntimeClass(final Class<?> clazz);
	/**
	 * determines the relationship between two class if one is the subtype of the other
	 * @param clazz generalization of subtype
	 * @param subtype specialization of clazz
	 * @return true if clazz is a supertype of subtype
	 */
	boolean isSubClass(Class<?> clazz, Class<?> subtype);
	/**
	 * gets a list of the classes which implement interface, or extends abstract
	 * class the assumption is that an interface
	 * or an abstract class is implemented locally, if not and hopefully
	 * not the case, then the method should explore the classpath to
	 * find implementing classes in jar files loaded by the class loader
	 * when the JVM startup the application.
	 * @param clazz an interface or abstract class
	 * @return list of classes
	 * @throws IllegalArgumentException if the package of the class
	 * is not in the classpath
	 */
	List<Class<?>> getSubClasses(final Class<?> clazz) throws IllegalArgumentException;
	/**
	 * Builds an <b>unordered</b> array of all interface and object classes that
	 * are generalizations of the provided class.
	 * <p>
	 * Both <code>clazz</code> itself and <code>java.lang.Object</code> are removed by default because they are redundant,
	 * if you require to include them, then use {@link ClassPathInterface#getSuperClasses(Class, boolean, boolean)}
	 * </p>
	 *
	 * @param classObject the class to find generalization of.
	 * @return an array of class objects.
	 * @see {@link ClassPathInterface#getSuperClasses(Class, boolean, boolean)}
	 */
	List<Class<?>> getSuperClasses(Class<?> clazz);
	/**
	 * Builds an <b>unordered</b> array of all interface and object classes that
	 * are generalizations of the provided class.
	 * @param includingSelf whether or not to include the same class in the set as a superclass of itself
	 * @param includingObject whether or not to include the <code>java.lang.Object</code> class in the set as a superclass of itself
	 * @param classObject the class to find generalization of.
	 * @return an array of class objects.
	 * @see {@link ClassPathInterface#getSuperClasses(Class)}
	 */
	List<Class<?>> getSuperClasses(Class<?> clazz, boolean includingSelf, boolean includingObject);
	/**
	 * Retrieves all interfaces implemented by a specified interface
	 * including all recursively extended interfaces and the classes supplied
	 * in the parameter.
	 * @param childInterfaces a set of interfaces
	 * @return Class[] an array of interfaces that includes those specified
	 * in childInterfaces plus all of those interfaces' super interfaces
	 */
	Class<?>[] getSuperInterfaces(Class<?>[] childInterfaces);
	/**
	 * gets array of classes which are in a given package
	 *
	 * @param  packageName The base package
	 * @return The classes
	 * @throws ClassNotFoundException
	 */
	Class<?>[] getClasses(String packageName) throws ClassNotFoundException;
	/**
	 * gets any direct sub-class of a given class
	 * @param aclazz super class
	 * @return a sub-class of the given class
	 */
	Class<?> getDirectSubClass(Class<?> aclazz);
	/**
	 * removes the packages that are included in classpath
	 * @param classpath a classpath entry
	 */
	void removeClassPathEntry(String classpath);


}